#include "httpmgr.h"
#include "QNetworkReply"

HttpMgr::HttpMgr()
{
    //连接http请求和完成信号，信号槽机制保证队列消费
    //这就是连接同一个对象中的某个信号与槽函数
    connect(this, &HttpMgr::sig_http_finish, this, &HttpMgr::slot_http_finish);
}

//发送消息
//请求--回复：客户端是请求reques，服务端是回复reply
//这一层只处理服务端是否回复正确的消息回来，具体的前端响应还是发送到指定的模块进行显示
//require:请求  reply:回复   客户端
//require:客户端的请求   reply：返回给客户端的回复    服务端

//调用网络底层接口发送消息
//注册信号回调函数：当前消息的reply---->回调函数，使用对应的回调进行处理消息回复，这里会更具各个层进行解耦然后进行调用，所以需要给出模块ID
//使用模块ID和re_ID ,就可以从两个维度进行回调处理，比如模块m个，repl——ID n个，一共可以形成m*n个底层处理函数，
void HttpMgr::PostHttpreq(QUrl url, QJsonObject json, ReqId req_id, Modules mod)
{
    //1.http对象，封装消息，封装头，发送(异步)，同时注册消息回收
    //创建一个HTTP POST请求，并设置请求头和请求体
    QByteArray data = QJsonDocument(json).toJson();     //序列化
    //通过url构造请求，URL是后端调用的第一层接口，类似于远程调用的函数名字
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(data.length()));
    //发送请求，并处理响应, 获取自己的智能指针，构造伪闭包并增加智能指针引用计数
    auto self = shared_from_this();

    QNetworkReply * reply = _manager.post(request, data);      //发送序列花之后的结果
    //设置信号和槽等待发送完成,这里使用事件机制，将reply的QNetworkReply::finished事件注册，回调函数是一个lambda函数，之所以把自己传入进去，为了防止二次析构


    //req_id,mod也只是为了客户端而使用，不会传送到后端，用他们是为了方便的传送到  客户端各个模块（MOD）下，通过REQ_ID调用函数，以及最终展示效果.
    QObject::connect(reply, &QNetworkReply::finished, [reply, self, req_id, mod](){
        //处理错误的情况
        if(reply->error() != QNetworkReply::NoError){
            qDebug() << reply->errorString();
            //发送信号通知完成,通过信号，发送到指定的模块进行操作，就是解耦合
            emit self->sig_http_finish(req_id, "", ErrorCodes::ERR_NETWORK, mod);
            reply->deleteLater();
            return;
        }

        //无错误则读回请求
        QString res = reply->readAll();

        //这里可以解析，或者你准备待会进行解析也是可以的，因为服务端带回来更多的信心

        //发送信号通知完成
        emit self->sig_http_finish(req_id, res, ErrorCodes::SUCCESS,mod);
        reply->deleteLater();
        return;
    });



}

HttpMgr::~HttpMgr()
{

}

//这一层处理的是:更具模块决定接下来发送到哪个模块进行消息处理
//刚刚上一层处理了是否得到回复，接下来是根据模块信息发送到指定的模块进行处理
//这里都是信号的传递，逐步的处理，这里使用的其实是世家机制，通过信号传递信息，是一种很金苗的是粗粒
//仔细观察有点类似于回调
void HttpMgr::slot_http_finish(ReqId id, QString res, ErrorCodes err, Modules mod)
{
    if(mod == Modules::REGISTERMOD){
        //发送信号通知指定模块http响应结束
        emit sig_reg_mod_finish(id, res, err);
    }
    //也有可能是其他的模块的
    if(mod==Modules::RESETPASSWDMOD)
    {
        emit sig_reset_mode_finish(id,res,err);
    }

    if(mod==Modules::LOGINMOD)
    {
        emit sig_login_mod_finish(id,res,err);
    }
}
